#ifndef _CLISTWIDGET_H_
#define _CLISTWIDGET_H_

#include <buola/widgets/cwidget.h>
#include <buola/gui/cicon.h>
#include <buola/image/cimage.h>

namespace buola { namespace gui {

///\addtogroup widgetclass

////////////////////////////////////////////////////////////////////////////

/// list widget class

///
///
///
////////////////////////////////////////////////////////////////////////////

class CListWidget : public CWidget
{
public:
    struct SField
    {
        int mIndex;
        CPropertyField *mField;

        double mX;
        double mW;
        double mMinW;
    };

    struct SItem
    {
        SItem(CListWidget *pList);
        ~SItem();

        //Setting values
    protected:
        void AddField(CPropertyField*);

    public:
        UAny& Value(int);
        std::wstring ValueAsText(int);

        const std::wstring &GetText()       {   return mText;   }
        void SetText(const std::wstring &pText);

        const PIcon GetIcon()           {   return mIcon;   }
        void SetIcon(PIcon pIcon);
    
        const img::CPicture &GetImage()     {   return mImage;  }
        void SetImage(const img::CPicture &pImage);

        const std::wstring &GetGroup()                  {   return mGroup;      }
        void SetGroup(const std::wstring &pGroup);

        SItem &operator=(const SItem &pOther);

        CListWidget *mList;
        TID mID;

        std::wstring mGroup;

        std::wstring mText;
        PIcon mIcon;
        img::CPicture mImage;

        std::vector<std::unique_ptr<UAny>> mValues;
    
        //renderer data
        void *mRendererData;

        //Properties
        bool mSelected;

        friend class CListWidget;
    };

    struct SSorter
    {
        SSorter(bool pReverse)
            :   mReverse(pReverse)
        {
        }

        bool operator()(SItem *p1,SItem *p2);

        bool mReverse;
    };

protected:
//! \name constructor and destructor
//@{
    CListWidget()
        :   mLWNextIndex(0x1000000),
            mLWSelected(0),
            mMainName(L"Name")
    {
    }

    virtual ~CListWidget()
    {
    }
//@}

    void LWCopyList(CListWidget *pOther);

protected:
//@{
    int GetFieldNum(int);
    int GetItemNum(TID);
//@}
    
public:
//! \name fields
//@{
    int AddField(CPropertyField*,int,int=100);  
    bool RemoveField(int);
    void RemoveAllFields();

    int GetFieldCount()                 {   return mLWF.size(); }
    const std::vector<SField*> &GetFields() {   return mLWF;            }
//@}

//! \name items
//@{
    SItem *NewItem(const std::wstring&,PIcon=nullptr,TID=INT_MIN);
    void AddItem(SItem*);
    SItem *AddItem(const std::wstring&,PIcon=nullptr,TID=INT_MIN);
    void AddItems(const std::vector<std::wstring>&,PIcon=nullptr,TID=INT_MIN);
    void ReplaceItem(SItem *pWhich,SItem *pWith);
    bool RemoveItemByID(TID);
    void RemoveAllItems();

    int GetItemCount()                      {   return mLWI.size(); }
    const std::vector<SItem*> &GetItems()   {   return mLWI;            }

    void SortItems();
//@}

//! \name groups
//@{
    void AddGroup(const std::wstring &pName);
    void RemoveGroup(const std::wstring &pName);
    const std::vector<std::wstring> &GetGroups()    {   return mLWGroups;           }
//@}

//! \name finding and retrieving items 
//@{
    TID GetSelID();
    std::wstring GetSelText();
    SItem *GetSelItem();

    SField *GetField(int);
    SItem *FindItem(const std::wstring&);
    SItem *GetItemByID(int);
    SItem *GetItemByPos(int);
    int GetItemPos(SItem *pItem);
//@}

    const std::wstring &GetMainName()           {   return mMainName;   }
    void SetMainName(const std::wstring& pName) {   mMainName=pName;    }

//! \name selection
//@{
    virtual void SelectItem(SItem*);
    virtual void ToggleItem(SItem*);
    virtual void SelectItems(int,SItem**);

    virtual void SelectItemByID(TID);
    virtual void ToggleItemByID(TID);

    virtual void SelectItemByName(const std::wstring &pName);
    virtual void ToggleItemByName(const std::wstring &pName);

    virtual void SelectAll();
    virtual void UnselectAll();
//@}

//! \name internal events
//@{
    virtual void OnItemSelected(SItem*)     {}
    virtual void OnListChanged()            {}
    virtual void OnItemAdded(SItem*)        {}
    virtual void OnItemChanged(SItem*)      {}
    virtual void OnItemRemoved(SItem*)      {}
    virtual void OnLWBigChange()            {}
    virtual void OnLWFieldsChanged()        {}
//@}

protected:
    std::vector<SField*> mLWF;
    std::vector<SItem*> mLWI;
    std::vector<std::wstring> mLWGroups;

    int mLWNextIndex;
    int mLWSelected;

    std::wstring mMainName;
};

/*namespace gui*/ } /*namespace buola*/ }

#endif
